package Test.MQ.ACK;

import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Component;
import com.rabbitmq.client.Channel;

/**
 * 关键点说明
 * AcknowledgeMode:
 *
 * AUTO: 自动确认，消息一旦被消费（无论是否抛出异常），都会自动确认
 *
 * MANUAL: 手动确认，需要显式调用channel.basicAck()或channel.basicNack()
 *
 * 手动ACK的三种操作:
 *
 * basicAck: 确认消息处理成功
 *
 * basicNack: 拒绝消息，可以设置是否重新入队
 *
 * basicReject: 拒绝消息（老版本方法）
 *
 * 异常处理:
 *
 * 手动ACK模式下，务必捕获异常并决定是确认还是拒绝消息
 *
 * 拒绝消息时，可以根据业务需求决定是否重新入队
 *
 * 性能考虑:
 *
 * 自动ACK模式性能更高，但消息可能会丢失（如果消费者处理失败）
 *
 * 手动ACK模式更可靠，但性能稍低
 *
 * 通过这种方式，你可以为不同的队列灵活配置ACK模式，根据业务需求平衡可靠性和性能
 */
@Component
public class MessageListener {

    // 自动ACK的消息处理
    @RabbitListener(queues = RabbitMQConfig.AUTO_ACK_QUEUE, 
                   containerFactory = "autoAckContainerFactory")
    public void handleAutoAckMessage(String message) {
        System.out.println("自动ACK处理消息: " + message);
        // 不需要手动ACK，Spring会自动确认
    }

    // 手动ACK的消息处理
    @RabbitListener(queues = RabbitMQConfig.MANUAL_ACK_QUEUE, 
                   containerFactory = "manualAckContainerFactory")
    public void handleManualAckMessage(String message, Channel channel, 
                                     Message amqpMessage) throws Exception {
        try {
            System.out.println("手动ACK处理消息: " + message);
            // 业务处理逻辑
            
            // 处理成功，手动确认消息
            channel.basicAck(amqpMessage.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            System.err.println("消息处理失败: " + e.getMessage());
            // 处理失败，拒绝消息并重新入队
            channel.basicNack(amqpMessage.getMessageProperties().getDeliveryTag(), false, true);
            
            // 或者拒绝消息并丢弃
            // channel.basicReject(amqpMessage.getMessageProperties().getDeliveryTag(), false);
        }
    }
}